package org.lcp.gatlingqueue.impl.part;

import org.lcp.gatlingqueue.interfaces.part.Barrel;
import org.lcp.gatlingqueue.interfaces.part.Element;

/**
 * 先进先出队列的实现 (队列样式图在接口中有说明)
 * 
 * 指针链表实现，当前枪管包含下一个枪管的地址
 * 
 * @author lcp
 * 
 */
@SuppressWarnings({ "rawtypes", "hiding", "unchecked" })
public class BarrelImpl<T> implements Barrel<T> {

	// /当前枪管的编号
	private int number = -1;

	// 下一个枪管
	private Barrel next;

	// 子弹链表，队列的实现
	private Element<T> head, tail;

	// 队列中的子弹数量
	private int count = 0;

	/**
	 * 构造函数
	 */
	public BarrelImpl(int barrelNumber) {
		this.number = barrelNumber;
	}

	@Override
	public synchronized void in(T object) {
		
		if (null == tail && null == head) {
			// 队列空，初始化
			Bullet<T> current = new Bullet<T>();
			current.setValue(object);
			tail = current;
			head = current;
			count++;
			return;
		}

		// 得到tail
		Element<T> current = tail;
		// tail 追加一个
		tail = new Bullet<T>();
		tail.setValue(object);
		current.setNext(tail);
		count++;

	}

	@Override
	public T out() {
		if (head == null) {
			// 队列空
			return null;
		}
		Element<T> current = head;
		// 指针转到next
		head = head.getNext();
		count--;
		return (T) current.getValue();
	}

	/**
	 * 得到一份sequeue的copy
	 */
	public T[] getSequeueCopy() {
		Object[] array = new Object[count];
		Element<T> current = head;
		for (int i = 0; i < count; i++) {
			array[i] = current.getValue();
			current = current.getNext();
		}
		return (T[]) array;
	}

	@Override
	public Barrel<T> getNext() {

		return next;
	}

	@Override
	public void setNext(Barrel<T> barrel) {
		this.next = barrel;
	}

	@Override
	public int getNumber() {
		return number;
	}

	/**
	 * 子弹(用于消息封装)
	 * 
	 * 内部类：一种枪管走一种子弹，一种队列走一种消息封装
	 * 
	 * @author lcp
	 * 
	 * @param <T>
	 */
	private class Bullet<T> implements Element<T> {

		T value;
		Bullet next;

		@Override
		public Bullet<T> getNext() {
			return next;
		}

		@Override
		public void setNext(Element<T> element) {
			next = (Bullet<T>) element;

		}

		@Override
		public void setValue(T value) {
			this.value = value;

		}

		@Override
		public T getValue() {
			return value;
		}
	}

}
